//策略模式的组成
//1.第一个部分一组策略类，策略类封装了具体的算法，并负责具体的计算过程
//2.第二个部分是环境类Context，Context接受客户的请i去，随后把请求委托给某一个策略类

const strategies = {
  isNonEmpty: function (value, errMsg) {
    if (value === "") {
      return errMsg;
    }
  },
  minLenth: function (value, length, errMsg) {
    if (value.length < length) {
      return errMsg;
    }
  },
  isMobile: function (value, errMsg) {
    if (!/^1[3|5|8][0-9]{9}$/.test(value)) {
      return errMsg;
    }
  }
};

form.onsubmit = function () {
  const validator = new Validator();
  validator.add(form.userName, "isNonEmpty", "用户名不能为空");
  validator.add(form.password, "minLength:6", "密码长度不能少于6位");
  validator.add(form.phoneNumber, "isMobile", "手机号码格式不正确");
  const errMsg = validator.start();
  if (errMsg) {
    alert(errMsg);
    return false;
  }
};

class Validator {
  constructor() {
    this.cache = [];
  }
  add(dom, rule, errMsg) {
    const arr = rule.split(":");
    this.cache.push(() => {
      const strategy = arr.shift();
      arr.unshift(dom.value);
      arr.push(errMsg);
      return strategies[strategy].apply(dom, arr);
    });
  }
  start() {
    for (let i = 0; i < this.cache.length; i++) {
      const msg = this.cache[i]();
      if (msg) return msg;
    }
  }
}




//优点
//1.可以有效地避免多重条件选择语句
//2.对开放-封闭原则完美支持，将算法封装在独立的strategy中，使得他们易于切换，易于理解，易于扩展
//3.可以使算法复用在系统的其他地方，避免许多重复的复制张贴工作

//缺点
//1.使用策略模式会在程序中增加许多策略类或策略对象
//2.要使用策略模式必须了解所有的strategy，裂解他们的不同点，我们才能选择一个适合的strategy。
